# encoding: utf-8
"""
!/usr/bin/python3
@Author: Gao Shuo
@Time: 2019/3/29 14:40 
@ReadMe:
    Input: 
    Output: 
"""
from mesa.datacollection import DataCollector
from mesa.space import MultiGrid
from mesa.time import RandomActivation

from mesa import Agent, Model



class MoneyAgent(Agent):
    """ An agent with fixed initial wealth."""
    def __init__(self, unique_id, model):
        super().__init__(unique_id, model)
        self.wealth = 1
        self.unique_id=unique_id

    def step(self):
        print('My id is: ', self.unique_id)
        print('my wealth is: ', self.wealth)
        #给随便一个人钱
        # if self.wealth == 0:
        #         return
        #     other_agent = self.random.choice(self.model.schedule.agents)
        #     other_agent.wealth += 1
        #     self.wealth -= 1
        self.move()
        if self.wealth > 0:
            self.give_money()

    # 移动到邻居
    def move(self):
        possible_steps = self.model.grid.get_neighborhood(
            self.pos,
            moore=True, #包含对角线
            include_center=False)
        new_position = self.random.choice(possible_steps)
        self.model.grid.move_agent(self, new_position)
    # 给钱
    def give_money(self):
        cellmates = self.model.grid.get_cell_list_contents([self.pos])
        if len(cellmates) > 1:
            other = self.random.choice(cellmates)
            other.wealth += 1
            self.wealth -= 1

def compute_gini(model):
    agent_wealths = [agent.wealth for agent in model.schedule.agents]
    x = sorted(agent_wealths)
    N = model.num_agents
    B = sum( xi * (N-i) for i,xi in enumerate(x) ) / (N*sum(x))
    return (1 + (1/N) - 2*B)

class MoneyModel(Model):
    """A model with some number of agents."""
    def __init__(self, N, width, height):
        self.num_agents = N
        self.grid = MultiGrid(width, height, True)
        self.schedule = RandomActivation(self)
        self.running = True

        # Create agents
        for i in range(self.num_agents):
            a = MoneyAgent(i, self)
            self.schedule.add(a)
            # Add the agent to a random grid cell
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(a, (x, y))

        self.datacollector = DataCollector(
            model_reporters={"Gini": compute_gini},  # A function to call
            agent_reporters={"Wealth": "wealth"})  # An agent attribute

    def step(self):
        self.datacollector.collect(self)
        self.schedule.step()



